Fork me on GitHub

深入Vue响应式原理

对于 Vue 响应式的疑惑:Vue 为什么不能检测到对象属性的添加或删除?为什么不支持通过索引设置数组成员?

Vue官方响应式原理:

避坑指南

对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app">
<p>{{msg}}</p>
<p>{{student.bob}}</p>
<p>{{student.kitty}}</p>
</div>
<script>
let vm = new Vue({
el: '#app',
data: { //只有预先定义好的数据,才能做相应reactive
msg: 'hello',
student: {
bob: 123
}
}
})
// kitty 并未预先定义,这样做是不能响应的
// vm.student.kitty = '我是新加的'
</script>

解决办法一:调用Vue的静态方法set

1
2
3
4
Vue.set(targetObj,prop,value)
setTimeout(function () {
Vue.set(vm.student, 'kitty', 456)
}, 2000)

解决办法二:调用实例上的方法

1
vm.$set(vm.student, 'kitty', '456')

解决办法三:改写预定义属性的值,重新赋值

1
2
3
4
5
6
7
vm.student = {
...vm.student,
kitty: 456
}
// 或者
vm.student = Object.assign({}, vm.student, { kitty: 456 })
vm.student = Object.assign(vm.student, { kitty: 456 })

数组

1
2
3
4
5
6
7
8
9
let vm = new Vue({
el: '#app',
data: { //只有预先定义好的数据,才能做相应reactive
list: [1, 2, 3]
}
})

// 直接通过下标改变数组的值是监控不到的,无法更新视图
vm.list[0] = '999'

解决办法:提供了观察数组的变异方法,使用这些方法会触发视图更新,
push(),pop()|shift(),unshift()|splice,sort()

1
2
3
// 通过splice修改数组

vm.list.splice(0, 1, 999);

Vue响应式原理

上面的做法虽然避坑,但是…为什么呢?找原因就要思考一下Vue如何实现的响应式。

Vue 的数据劫持依赖于 Object.defineProperty,所以一定是因为它的某些特性,才引起这个问题。

🌰 举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 定义cb函数,模拟视图更新操作,调用它即表示更新视图
function cb(val) {
console.log(val, '视图更新啦');
}

function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true, // 属性可枚举
configurable: true, // 属性可被修改/删除
get: function reactiveGetter() {
return val;
},
set: function reactiveSetter(newVal) {
if (newVal === val) return;
cb(newVal);
}
})
}

function observer(value) {
if (!value || (typeof value !== 'object')) {
return;
}

Object.keys(value).forEach((key) => {
defineReactive(value, key, value[key]);
})
}

class Vue {
constructor(opt) {
this._data = opt.data;
observer(this._data);
}
}

let vm = new Vue({
data: {
test: 'I am test.'
}
})

本文标题:深入Vue响应式原理

文章作者:tongtong

发布时间:2019年04月12日 - 10:04

最后更新:2019年04月30日 - 18:04

原始链接:https://ilove-coding.github.io/2019/04/12/[待完成]深入Vue响应式原理/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!
-------------本文结束-------------